#ifndef __REDCELL_COMMON_HPP__
#define __REDCELL_COMMON_HPP__

#include <string>
#include <sstream>
#include <stdexcept>

namespace redcell {
  typedef long long Integer;
  typedef double Real;
  typedef std::string String;
  typedef std::size_t Key;

  typedef long long Oid;

  enum {
    FALSE = 0,
    TRUE = 1,
  };

  enum {
    F_TRUE = 0x01,
    F_FALSE = 0x02,
    F_POS = 0x03,
    F_NEG = 0x04,
    F_FLOAT = 0x05,
    F_DOUBLE = 0x06,
    F_STR = 0x07,
    F_NIL = 0x08,
    F_SUB = 0x09,
    F_EMPTYSUB = 0x0a,
    F_END = 0x0d,
    F_KEYSKIP = 0x0e,
    F_PADDING = 0x0f,
  };


  enum {
    NIL = 0x00,
    INTEGER = 0x01,
    REAL = 0x02,
    STRING = 0x08,
    TABLE = 0x09,
  };

  inline String typeToString(const char type) {
    switch (type) {
    case NIL: return "NIL";
    case INTEGER: return "INTEGER";
    case REAL: return "REAL";
    case STRING: return "STRING";
    case TABLE: return "TABLE";
    }
  }

  struct Error: public std::runtime_error {
    Error(const String &what = "error"): std::runtime_error("redcell: " + what) {}
  };


  struct TypeError: public Error {
    static String formatWhat(const char wrong, const char right) {
      std::ostringstream os;
      os << "Type: Attempting to get " 
	 << typeToString(wrong) 
	 << " from " << typeToString(right);
      return os.str();
    }

    TypeError(const char wrong, const char right): Error(formatWhat(wrong, right)) {}
  };


  struct KeyError: public Error {
    static String formatWhat(const Key key) {
      std::ostringstream os;
      os << "Key: " << key << " not exist";
      return os.str();
    }

    KeyError(const Key key): Error(formatWhat(key)) {}
  };


  struct MarshalError: public Error {
    MarshalError(const String &what = "error"): Error("Marshal: " + what) {}
  };

  /*
  struct StreamError: public Error {
    StreamError(const String &what = "error"): Error("Stream: " + what) {}
  };
  */

}


#endif
